﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls;
using System.Data;
using System.Configuration;
using ASBCC.Workflow.K2Manager;
using ASBCC.Database.Entity;
using ASBCC.Database.Service;


namespace ASBCC.Workflow.Client
{
    public class WorkflowControllerBase : IWorkflowController
    {
        #region Members

        private IWorkflowPage _workflowPage;
        private IAppForm _appForm;
        private MyActivityTableEntity _myActivity;
        
        private Flow_ProcessConfigTableEntity _currentProcessConfig; // Current User is MyActivity Owner
        private Flow_ProcessConfigTableEntity _runningProcessConfig; // Current User is Viewer
        private Flow_ProcessConfigTableEntity _submissionProcessConfig; 
        private Flow_ProcessConfigTableEntity _endProcessConfig; // 

        private int _procId;
        private string _submissionActivityName;
        private K2User _reportToOfActualUser;
        private List<string> _runningActivityNameList;

        #endregion

        #region Constructor

        public WorkflowControllerBase(IWorkflowPage workflowPage, IAppForm appForm, MyActivityTableEntity myActivity)
        {
            _workflowPage = workflowPage;
            _appForm = appForm;
            _myActivity = myActivity;
        }

        #endregion

        #region Helper

        private string GetProcessName()
        {
            return K2Helper.GetProcessName(GetProcName());
        }

        private K2Console GetK2Console()
        {
            string actionType = GetActionType();
            string auditDestination = GetAuditDestination();
            string comment = GetComment();

            K2Console console = new K2Console();

            //ActionInfo
            console.ActionInfo.ActionType = actionType;
            console.ActionInfo.ActionName = GetActionName(actionType);

            //Added by GJ 2011-6-15 判断是否选择了抄送人
            if (string.Compare(string.Empty, K2AuditDestination.GetCcuser(auditDestination), true) != 0)
            {
                console.CcUser = K2AuditDestination.GetCcuser(auditDestination);
            }
            else
            {
                console.CcUser = string.Empty;
            }

            console.AuditDestination = GetAuditDestination(auditDestination);
            console.Comment = comment;

            BuildK2AppForm(console.AppForm);
            BuildK2WorkItem(console.WorkItem);
            BuildK2DataFields(console.DataFields);
            return console;
        }

        private K2AuditDestination GetAuditDestination(string auditDestination)
        {
            return K2AuditDestination.LoadText(auditDestination);
        }

        private string GetActionName(string actionType)
        {
            string actionName = "";
            switch (actionType)
            {
                case K2ActionType.Back:
                    actionName = K2ActionName.Back;
                    break;
                case K2ActionType.Cancel:
                    actionName = K2ActionName.Cancel;
                    break;
                default:
                    actionName= K2ActionName.Submit;
                    break;
            }
            return actionName;

        }

        private void InitActionButtonVisibilityByDefault(Button actionButton)
        {
            actionButton.Visible = false;
        }

        private void InitActionButtonVisibilityByProcessConfig(Button actionButton)
        {
            string actionType = WorkflowUtility.GetActionType(actionButton);
            string actionTypeItem = ";" + actionType + ";";

            Flow_ProcessConfigTableEntity processConfig = null;

            if (IsDraft())
            {
                processConfig = GetSubmissionProcessConfig();
            }
            if (IsEnd())
            {
                processConfig = GetEndProcessConfig();
            }
            else
            {
                string currentActivityName = GetCurrentActivityName();
                bool currentUserIsOwner = !string.IsNullOrEmpty(currentActivityName);
                if (currentUserIsOwner)
                {
                    processConfig = GetCurrentProcessConfig();
                }
                else // Current Is Viewer
                {
                    bool workflowRelated = WorkflowUtility.IsWorkflowRelated(actionButton);
                    Flow_ProcessConfigTableEntity runningProcessConfig = GetRunningProcessConfig();
                    if (runningProcessConfig != null)
                    {
                        string actionButtons = ";" + runningProcessConfig.ActionButtons + ";";
                        if (workflowRelated)
                        {
                            if (actionType == K2ActionType.Withdraw || actionType == K2ActionType.Drawback)
                            {
                                if (actionButtons.Contains(actionTypeItem)) actionButton.Visible = true;
                            }
                        }
                        else
                        {
                            if (actionType != K2ActionType.Save)
                            {
                                if (actionButtons.Contains(actionTypeItem)) actionButton.Visible = true;
                            }
                        }
                    }
                }
            }

            if (processConfig != null)
            {
                string actionButtons = ";" + processConfig.ActionButtons + ";";
                if (actionButtons.Contains(actionTypeItem)) actionButton.Visible = true;
            }
        }

        public virtual void InitActionButtonVisibility(Button actionButton)
        {
            string actionType = WorkflowUtility.GetActionType(actionButton);

            if (!actionButton.Visible) return;

            bool workflowRelated = WorkflowUtility.IsWorkflowRelated(actionButton);

            bool viewOnly = GetWorkflowPage().IsViewOnly();
            if (viewOnly) //只读的情况下，流程相关的按钮都不可见
            {
                if (workflowRelated)
                {
                    actionButton.Visible = false;
                }
                else
                {
                    if (actionType == K2ActionType.Save || actionType == K2ActionType.Log)
                    {
                        actionButton.Visible = false;
                    }
                }

                return;
            }

            if (IsDraft()) //处于草稿状态，跟流程尚未关联
            {
                //草稿状态下，跟流程相关的节点不可见，但Submit按钮除外
                if (actionType != K2ActionType.Submit)
                {
                    if (workflowRelated) actionButton.Visible = false;
                }

                //草稿状态下，跟Log按钮不可见，因为尚未提交，不存在流程日志
                if (actionType == K2ActionType.Log)
                {
                    actionButton.Visible = false;
                }

                return;
            }

            if (IsInProcess()) //流程中
            {
                string currentActivityName = GetCurrentActivityName();
                bool currentUserIsOwner = !string.IsNullOrEmpty(currentActivityName);
                bool currentUserIsCreatorOrApplicant = CurrentUserIsCreatorOrApplicant();

                if (IsAskedForMore())
                {
                    if (workflowRelated)
                    {
                        if (actionType != K2ActionType.ReplyAskForMore)
                        {
                            actionButton.Visible = false;
                        }
                    }
                }
                else if (IsForwardedBack())
                {
                    if (workflowRelated)
                    {
                        if (actionType != K2ActionType.ReplyForwardBack)
                        {
                            actionButton.Visible = false;
                        }
                    }
                }
                else if (IsRejected())
                {
                    if (workflowRelated)
                    {
                        if (actionType != K2ActionType.Resubmit && actionType != K2ActionType.Discard)
                        {
                            actionButton.Visible = false;
                        }
                    }
                }
                else if (IsWithdrawn())
                {
                    if (workflowRelated)
                    {
                        if (actionType != K2ActionType.Resubmit && actionType != K2ActionType.Discard)
                        {
                            actionButton.Visible = false;
                        }
                    }
                }
                else //正常审批 
                {
                    if (workflowRelated)
                    {
                        if (actionType != K2ActionType.Approve && actionType != K2ActionType.Reject && actionType != K2ActionType.Acknowledge && actionType != K2ActionType.PostSubmit && 
                            actionType != K2ActionType.Validate && actionType != K2ActionType.Upload && 
                            actionType != K2ActionType.Review && actionType != K2ActionType.Forward &&
                            actionType != K2ActionType.AskForMore && actionType != K2ActionType.Cancel)
                        {
                            actionButton.Visible = false;
                        }
                    }
                }

                if (currentUserIsCreatorOrApplicant)
                {
                    if (!IsPostSubmitted())
                    {
                        if (actionType == K2ActionType.PostSave)
                        {
                            actionButton.Visible = false;
                        }
                    }
                    //如果当前用户是创建者或申请者，并且流程状态为非被退回或被撤回状态，Withdraw按钮可见
                    if (actionType == K2ActionType.Withdraw)
                    {
                        actionButton.Visible = !IsRejected() && !IsWithdrawn();
                    }


                }
                else
                {
                    if (actionType == K2ActionType.PostSave)
                    {
                        actionButton.Visible = false;
                    }
                }
            }
            else if (IsEnd())
            {
            }

            if (actionType == K2ActionType.Drawback)
            {
                bool canDrawback = CanDrawback();
                string processStatus = GetAppForm().ProcessStatus;
                if (canDrawback && (processStatus == ProcessStatusConsts.Approved || processStatus == ProcessStatusConsts.Reviewed || processStatus == ProcessStatusConsts.Rejected))
                {
                    actionButton.Visible = true;
                }
                else
                {
                    actionButton.Visible = false;
                }
            }
        }


        private Flow_ActionRecordTableEntity GetLastActoinRecord()
        {
            int procInstId = GetAppForm().ProcInstId;
            if (procInstId <= 0) return null;
            return K2DataHelper.GetLastActionRecord(procInstId);
        }

        private bool CanDrawback()
        {
            Flow_ActionRecordTableEntity lastActionRecord = this.GetLastActoinRecord();
            if (lastActionRecord == null) return false;
            K2User currentUser = GetCurrentUser();
            if (currentUser == null) return false;
            return currentUser.UserId == lastActionRecord.OwnerID;
        }

        private List<int> GetAuditUsersFromProcessConfig(Flow_ProcessConfigTableEntity processConfig)
        {
            if (processConfig == null) return null;
            if (string.IsNullOrEmpty(processConfig.AuditUserSource))
            {
                throw new Exception(string.Format("Failed to invoke GetDestinationFromProcessConfig. AuditUserSource can not be null. ProcName={0}; ActivityName={1}", processConfig.ProcName, processConfig.ActivityName));
            }
            if (processConfig.AuditUserSource == AuditUserSourceConsts.Applicant)
            {
                K2User applicant = GetApplicant();
                if (WorkflowUtility.K2UserIsNull(applicant)) throw new Exception("Failed to GetDestinationFromProcessConfig. Applicant is null.");
                return new List<int>( new int[] { applicant.UserId } );
            }
            if (processConfig.AuditUserSource == AuditUserSourceConsts.ReportTo)
            {
                K2User reportTo = GetReportToOfActualUser();
                if (reportTo == null) throw new Exception("Failed to GetDestinationFromProcessConfig. ReportToOfActualUser is null.");
                return new List<int>(new int[] { reportTo.UserId });
            }
            if (processConfig.AuditUserSource == AuditUserSourceConsts.User)
            {
                string auditUsers = processConfig.AuditUsers;
                if (string.IsNullOrEmpty(auditUsers)) throw new Exception(string.Format("Failed to GetDestinationFromProcessConfig. AuditUsers is null. ProcName={0} ActivityName={1}", processConfig.ProcName, processConfig.ActivityName));
                string[] auditUserArr = auditUsers.Split(new char[] { K2AuditDestination.Consts.SEPARATOR_USER }, StringSplitOptions.RemoveEmptyEntries);
                List<int> users = new List<int>();
                foreach (string auditUser in auditUserArr)
                {
                    users.Add(Convert.ToInt32(auditUser.Trim()));
                }
                return users;
            }
            if (processConfig.AuditUserSource == AuditUserSourceConsts.Role)
            {
                string auditRole = processConfig.AuditRole;
                if (string.IsNullOrEmpty(auditRole)) throw new Exception(string.Format("Failed to GetDestinationFromProcessConfig. AuditRole is null. ProcName={0} ActivityName={1}", processConfig.ProcName, processConfig.ActivityName));
                List<int> users = GetUserInfosByRole(auditRole);
                if (users == null || users.Count == 0) throw new Exception(string.Format("Failed to GetUserInfosByRole. Role_CD={0}", auditRole));
                return users;
            }
            return null;
        }

        private List<int> GetUserInfosByRole(string role_cd)
        {
            EmployeeTableEntitySet set = K2DataHelper.GetUserInfosByROLE_CD(role_cd);
            if (set == null || set.Count == 0) return null;
            List<int> userList = new List<int>();
            foreach (EmployeeTableEntity userInfo in set)
            {
                userList.Add(userInfo.EmployeeID.Value);
            }
            return userList;
        }

        private string PreProcessFormUrl(string formUrl)
        {
            if (string.IsNullOrEmpty(formUrl)) return string.Empty;

            IWorkflowPage workflowPage = GetWorkflowPage();
            string appFormId_Key = workflowPage.GetRequestParamKey_AppFormId();
            string myActivityId_Key = workflowPage.GetRequestParamKey_MyActivityId();
            string rootUrl;
            Dictionary<string, string> queryStringParameters;
            WorkflowUtility.ParseUrl(formUrl, out rootUrl, out queryStringParameters);
            string foundAppFormId_Key = WorkflowUtility.FindKeyInDictionary(queryStringParameters, appFormId_Key, true);
            string foundMyActivityId_Key = WorkflowUtility.FindKeyInDictionary(queryStringParameters, myActivityId_Key, true);
            string foundRandom_Key = WorkflowUtility.FindKeyInDictionary(queryStringParameters, AppFormUrlKeyConsts.Random, true);
            if (string.IsNullOrEmpty(foundAppFormId_Key))
            {
                int appFormId = GetAppForm().AppFormId;
                queryStringParameters.Add(appFormId_Key, appFormId.ToString());
            }
            if (!string.IsNullOrEmpty(foundMyActivityId_Key))
            {
                queryStringParameters.Remove(foundMyActivityId_Key);
            }
            if (!string.IsNullOrEmpty(foundRandom_Key))
            {
                queryStringParameters.Remove(foundRandom_Key);
            }
            return WorkflowUtility.CombineUrl(rootUrl, queryStringParameters);
        }

        private string GetAuditDestination()
        {
            IWorkflowPage workflowPage = GetWorkflowPage();
            Dictionary<string, object> formArguments = workflowPage.GetFormArguments();
            string auditDestination;
            WorkflowUtility.TryGetDictionaryValue(formArguments, WorkflowKeyConsts.AuditDestination, out auditDestination);
            return auditDestination;
        }

   
        private K2AuditDestination GetK2AuditDestination()
        {
            IWorkflowPage workflowPage = GetWorkflowPage();
            Dictionary<string, object> formArguments = workflowPage.GetFormArguments();
            string auditDestination;
            WorkflowUtility.TryGetDictionaryValue(formArguments, WorkflowKeyConsts.AuditDestination, out auditDestination);
            return K2AuditDestination.LoadText(auditDestination);
        }

        private string GetComment()
        {
            IWorkflowPage workflowPage = GetWorkflowPage();
            Dictionary<string, object> formArguments = workflowPage.GetFormArguments();
            string comment;
            WorkflowUtility.TryGetDictionaryValue(formArguments, WorkflowKeyConsts.Comment, out comment);
            return comment;
        }

        private bool IsAuditDestinationAssigned()
        {
            IWorkflowPage workflowPage = GetWorkflowPage();
            Dictionary<string, object> formArguments = workflowPage.GetFormArguments();
            object objAssigned = formArguments[WorkflowKeyConsts.AuditDestinationAssgined];
            if (objAssigned != null && objAssigned.ToString() == "1") return true;
            return false;
        }

        #endregion

        #region Virtual Members

        public virtual void BuildAuditDestinationArgument(string actionType)
        {
            string auditDestination = string.Empty;
            string nextActivityName = GetNextActivityName();
            Flow_ProcessConfigTableEntity processConfig = K2DataHelper.GetProcessConfig(GetProcName(), nextActivityName);
            List<int> auditUserList = GetAuditUsersFromProcessConfig(processConfig);
            int[] auditUserArr = null;
            if (auditUserList != null) auditUserArr = auditUserList.ToArray();
            K2AuditDestination k2AuditDestination = new K2AuditDestination(nextActivityName, auditUserArr);
            auditDestination = k2AuditDestination.ExportText();
            Dictionary<string, object> formArguments = GetFormArguments();
            formArguments[WorkflowKeyConsts.AuditDestination] = auditDestination;
        }
       
        public virtual void InitActionButtonAttributes(Button actionButton)
        {
        }

        public virtual void InitActionButtonClientClick(Button actionButton)
        {
            string actionType = WorkflowUtility.GetActionType(actionButton);
            if (!actionButton.Visible) return;

            List<string> actionButtonList = new List<string>(
                new string[] { 
                    K2ActionType.Save,
                    K2ActionType.Edit
                });
            if (actionButtonList.Contains(actionType)) actionButton.OnClientClick = "var res=__wf_onActionClientClick();if(!res) return";

            List<string> actionButtonListWithComment = new List<string>(
                new string[] { 
                    K2ActionType.Approve,
                    K2ActionType.Reject,
                    K2ActionType.Review,
                    //K2ActionType.Forward,
                    //K2ActionType.ForwardBack,
                    //K2ActionType.ReplyForwardBack,
                    //K2ActionType.AskForMore,
                    K2ActionType.Validate,
                    K2ActionType.Upload,
                    K2ActionType.ReplyAskForMore,
                    K2ActionType.Drawback,
                    K2ActionType.Withdraw,
                    K2ActionType.Discard,
                    K2ActionType.Acknowledge
                });
            if (actionButtonListWithComment.Contains(actionType)) actionButton.OnClientClick = string.Format("var res=__wf_ActionClientClickWithComments('{0}',true);if(!res) return", ConfigurationManager.AppSettings["ApplicationBasePath"].TrimEnd('/'));

            switch (actionType)
            {
                case K2ActionType.Submit: 
                case K2ActionType.Resubmit:
                case K2ActionType.PostSubmit:
                    actionButton.OnClientClick = "var res=__wf_onActionClientClick(); if(!res) return; window.event.srcElement.disabled=true;";
                    break;
                case K2ActionType.Approve:
                    //actionButton.OnClientClick = "var res=__wf_onActionClientClick(); if(!res) return; window.event.srcElement.disabled=true;";
                    break;
                case K2ActionType.Validate:
                    // actionButton.OnClientClick = "var res=__wf_onActionClientClick(); if(!res) return; window.event.srcElement.disabled=true;";
                    break;
                case K2ActionType.Acknowledge:
                    break;
                case K2ActionType.Upload:
                    // actionButton.OnClientClick = "var res=__wf_onActionClientClick(); if(!res) return; window.event.srcElement.disabled=true;";
                    break;
                case K2ActionType.Reject: 
                    break;
                case K2ActionType.Review: 
                    break;
                case K2ActionType.Forward:
                    Flow_ProcessConfigTableEntitySet ds = Flow_ProcessConfigManager.SelectByCondition(string.Format(" ActivityName ='{0}' and ProcName='{1}' ", GetCurrentActivityName(), GetProcName()));
                    string aduitRole="";
                    if(ds!=null&&ds.Count>0)
                        aduitRole=ds[0].AuditRole;
                    actionButton.OnClientClick = string.Format("__wf_ActionClientClickWithComments_Forward('{0}',true,{1},'{2}','{3}'); return", ConfigurationManager.AppSettings["ApplicationBasePath"].TrimEnd('/'), GetAppForm().ProcInstId, GetCurrentActivityName(), aduitRole);
                    break;
                case K2ActionType.ForwardBack:
                    break;
                case K2ActionType.ReplyForwardBack: 
                    break;
                case K2ActionType.AskForMore:
                    actionButton.OnClientClick = string.Format("__wf_ActionClientClickWithComments_AskForMore('{0}',true,{1}); return", ConfigurationManager.AppSettings["ApplicationBasePath"].TrimEnd('/'), GetAppForm().ProcInstId);
                    break;
                case K2ActionType.ReplyAskForMore: 
                    break;
                case K2ActionType.Drawback: 
                    break;
                case K2ActionType.Withdraw:
                    actionButton.OnClientClick = "var res=confirm('确认撤回吗?\\nAre you sure to withdraw?'); if(!res) return;";
                    break;
                case K2ActionType.Discard:
                    actionButton.OnClientClick = "var res=__wf_onActionClientClick(); if(!res) return;";
                    break;
                case K2ActionType.Close:
                    actionButton.OnClientClick = "__wf_onActionClientClick_Close();";
                    break;
                case K2ActionType.Save: 
                    break;
                case K2ActionType.Edit: 
                    break;
                case K2ActionType.Log:
                    actionButton.OnClientClick = string.Format("__wf_doActionClientClick_Log('{0}',true,{1}); return", ConfigurationManager.AppSettings["ApplicationBasePath"].TrimEnd('/'), GetAppForm().ProcInstId);
                    break;
                case K2ActionType.Comment: 
                    break;
                case K2ActionType.Print: 
                    break;
            }
        }

        public virtual string GetNextActivityName()
        {
            ActivityLink activityLink = GetActivityLink();
            if (activityLink == null) return string.Empty;
            string currentActivityName = string.Empty;
            currentActivityName = GetCurrentActivityName();
            if ((IsDraft() || IsSubmitted())&&string.IsNullOrEmpty(currentActivityName))
            {
                currentActivityName = GetSubmissionActivityName();
            }
            //else
            //{
            //    currentActivityName = GetCurrentActivityName();
            //}
            ActivityLinkNode currentNode = activityLink.FindNode(currentActivityName);
            if (currentNode == null) return string.Empty;
            ActivityLinkNode lastChild = currentNode.LastChild;
            if (lastChild == null) return string.Empty;
            return lastChild.Value;
        }

        public virtual void BuildK2AppForm(K2AppForm k2AppForm)
        {
            IAppForm appForm = GetAppForm();
            k2AppForm.Applicant.UserId = appForm.Applicant.UserId;
            k2AppForm.Applicant.UserEn = appForm.Applicant.UserEn;
            k2AppForm.Applicant.UserCn = appForm.Applicant.UserCn;
            k2AppForm.ApplicationNo = appForm.AppFormNo;
            k2AppForm.Creator.UserId = appForm.Creator.UserId;
            k2AppForm.Creator.UserEn = appForm.Creator.UserEn;
            k2AppForm.Creator.UserCn = appForm.Creator.UserCn;
            K2User currentUser = GetCurrentUser();
            if (currentUser != null)
            {
                k2AppForm.CurrentUser.UserId = currentUser.UserId;
                k2AppForm.CurrentUser.UserEn = currentUser.UserEn;
                k2AppForm.CurrentUser.UserCn = currentUser.UserCn;
            }
            K2User delegateFrom = GetDelegateFrom();
            if (delegateFrom != null)
            {
                k2AppForm.DelegateFrom.UserId = delegateFrom.UserId;
                k2AppForm.DelegateFrom.UserEn = delegateFrom.UserEn;
                k2AppForm.DelegateFrom.UserCn = delegateFrom.UserCn;
            }
            k2AppForm.Folio = appForm.Folio;
            k2AppForm.Title = GetFormTitle();
            k2AppForm.FormId = appForm.AppFormId;

            Dictionary<string, object> formArguments = GetFormArguments();
            k2AppForm.ModuleName = formArguments[WorkflowKeyConsts.ModuleName].ToString();
        }

        public virtual void BuildK2DataFields(Dictionary<string, object> dataFields)
        {
            if (dataFields == null) return;
            Dictionary<string, object> formArguments = GetFormArguments();
            string formUrl = PreProcessFormUrl(formArguments[WorkflowKeyConsts.FormUrl].ToString());
            dataFields[WorkflowKeyConsts.FormUrl] = formUrl;
        }

        public virtual void BuildK2WorkItem(K2WorkItem workItem)
        {
            string actionType = GetActionType();
            Dictionary<string, object> formArguments = GetFormArguments();
            MyActivityTableEntity myActivity = GetMyActivity();
            if (myActivity == null)
            {
                if (IsDraft())
                {
                    workItem.ActivityName = ActivityNameConsts.Submission;
                }

                workItem.ProcInstId = GetAppForm().ProcInstId;
                if (actionType == K2ActionType.AskForMore)
                {
                    workItem.ProcInstId = (int)formArguments[WorkflowKeyConsts.AskformoreProcInstID];
                }
                workItem.ProcName = GetProcName();
            }
            else
            {
                workItem.ActInstDestId = myActivity.K2ActInstDestID ?? 0;
                if (actionType == K2ActionType.AskForMore)
                {
                    workItem.ActInstDestId = GetAppForm().ProcInstId;
                }
                workItem.ActivityName = myActivity.K2ActivityName;
                workItem.ArrvialDate = myActivity.ArrvialDate ?? DateTime.MinValue;
                workItem.Destination = myActivity.K2Destination;
                workItem.ProcInstId = myActivity.K2ProcInstID ?? 0;
                if (actionType == K2ActionType.AskForMore)
                {
                    workItem.ProcInstId = (int)formArguments[WorkflowKeyConsts.AskformoreProcInstID];
                }
                workItem.ProcName = GetProcName();
                workItem.MyActivityId = myActivity.MyActivityID ?? Guid.Empty;
                workItem.ActionRecordId = myActivity.ActionRecordID ?? Guid.Empty;
            }
        }

        public virtual void ExecuteActionDone()
        {
            string actionType = GetActionType();
            IAppForm appForm = GetAppForm();

            switch (actionType)
            {
                case K2ActionType.Submit:
                    appForm.ProcessStatus = ProcessStatusConsts.Submitted;
                    appForm.Status = AppFormStatusConsts.InProcess;
                    break;
                case K2ActionType.Approve:
                    appForm.ProcessStatus = ProcessStatusConsts.Approved;
                    appForm.Status = AppFormStatusConsts.InProcess;
                    break;
                case K2ActionType.Acknowledge:
                    appForm.ProcessStatus = ProcessStatusConsts.Acknowledge;
                    appForm.Status = AppFormStatusConsts.InProcess;
                    break;
                case K2ActionType.Validate:
                    appForm.ProcessStatus = ProcessStatusConsts.Validate;
                    appForm.Status = AppFormStatusConsts.InProcess;
                    break;
                case K2ActionType.Upload:
                    //appForm.ProcessStatus = ProcessStatusConsts;
                    //appForm.Status = AppFormStatusConsts.InProcess;
                    break;
                case K2ActionType.PostSubmit:
                    appForm.ProcessStatus = ProcessStatusConsts.PostSubmitted;
                    appForm.Status = AppFormStatusConsts.InProcess;
                    break;
                case K2ActionType.Review:
                    appForm.ProcessStatus = ProcessStatusConsts.Reviewed;
                    appForm.Status = AppFormStatusConsts.InProcess;
                    break;
                case K2ActionType.Reject:
                    appForm.ProcessStatus = ProcessStatusConsts.Rejected;
                    appForm.Status = AppFormStatusConsts.Rejected;
                    break;
                case K2ActionType.Withdraw:
                    appForm.ProcessStatus = ProcessStatusConsts.Withdrawn;
                    appForm.Status = AppFormStatusConsts.InProcess;
                    break;
                case K2ActionType.Drawback:
                    appForm.ProcessStatus = ProcessStatusConsts.Drawbacked;
                    appForm.Status = AppFormStatusConsts.InProcess;
                    break;
                case K2ActionType.Forward:
                    appForm.ProcessStatus = ProcessStatusConsts.Forwarded;
                    break;
                case K2ActionType.ForwardBack:
                    appForm.ProcessStatus = ProcessStatusConsts.ForwardedBack;
                    break;
                case K2ActionType.Resubmit:
                    appForm.ProcessStatus = ProcessStatusConsts.Submitted;
                    appForm.Status = AppFormStatusConsts.InProcess;
                    appForm.CurrentStep = GetNextActivityName();
                    break;
                case K2ActionType.AskForMore:
                    appForm.ProcessStatus = ProcessStatusConsts.AskedForMore;
                    appForm.Status = AppFormStatusConsts.AskedForMore;
                    break;
                case K2ActionType.ReplyAskForMore:
                    appForm.ProcessStatus = ProcessStatusConsts.RepliedAskForMore;
                    appForm.Status = AppFormStatusConsts.InProcess;
                    break;
                case K2ActionType.ReplyForwardBack:
                    appForm.ProcessStatus = ProcessStatusConsts.RepliedForwardBack;
                    break;
                case K2ActionType.Discard:
                    appForm.ProcessStatus = ProcessStatusConsts.Discarded;
                    appForm.Status = AppFormStatusConsts.Discarded;
                    break;
                default:
                    break;
            }
            K2AuditDestination k2AuditDestination = GetK2AuditDestination();
            if (k2AuditDestination != null && k2AuditDestination.ActivityDestinationList.Count > 0)
            {
                if (k2AuditDestination.ActivityDestinationList[0].ActivityName == ActivityNameConsts.End)
                {
                    appForm.ProcessStatus = ProcessStatusConsts.End;
                    appForm.Status = AppFormStatusConsts.End;
                }
            }
        }

        #endregion

        #region Public Members

        public IWorkflowPage GetWorkflowPage()
        {
            return _workflowPage;
        }

        public Dictionary<string, object> GetFormArguments()
        {
            return GetWorkflowPage().GetFormArguments();
        }

        public IAppForm GetAppForm()
        {
            if (_appForm == null) throw new Exception("Instance of IAppForm can not be null.");
            if (_appForm.AppFormId == 0)
                _appForm.AppFormId = _workflowPage.NewAppFormID;
            return _appForm;
        }

        public MyActivityTableEntity GetMyActivity()
        {
            return _myActivity;
        }

        /// <summary>
        /// 获取当前表单相关的MyActivity中的所有活动的节点（考虑到并发流程的情况）
        /// </summary>
        /// <returns></returns>
        public List<string> GetRunningActivityNameList()
        {
            if (_runningActivityNameList == null)
            {
                List<string> list = new List<string>();
                IAppForm appForm = GetAppForm();
                if (appForm != null && appForm.ProcInstId > 0)
                {
                    MyActivityTableEntitySet set = K2DataHelper.GetMyActivities(appForm.ProcInstId, new int[] { (int)MyActivityStatus.Normal });
                    foreach (MyActivityTableEntity entity in set)
                    {
                        string activityName = string.IsNullOrEmpty(entity.TargetActivityName) ? entity.K2ActivityName : entity.TargetActivityName;
                        if (!list.Contains(activityName))
                        {
                            list.Add(activityName);
                        }
                    }
                }
                _runningActivityNameList = list;
            }
            return _runningActivityNameList;
        }

        public string GetRunningActivityName()
        {
            List<string> list = GetRunningActivityNameList();
            if (list == null || list.Count == 0) return string.Empty;
            return list[0];
        }

        public IWorkflowActionPanel GetWorkflowActionPanel()
        {
            return _workflowPage == null ? null : _workflowPage.GetActionPanel();
        }

        public IWorkflowControl GetProcessStampControl()
        {
            return _workflowPage == null ? null : _workflowPage.GetProcessStampControl();
        }

        public string GetProcName()
        {
            return GetWorkflowPage().GetProcName();
        }

        /// <summary>
        /// 获取流程第一步的ActivityName
        /// </summary>
        /// <returns></returns>
        public string GetSubmissionActivityName()
        {
            if (string.IsNullOrEmpty(_submissionActivityName))
            {
                ActivityLink activityLink = GetActivityLink();
                ActivityLinkNode firstNode = activityLink.First;
                if (firstNode == null) return string.Empty;
                _submissionActivityName = firstNode.Value;
            }
            return _submissionActivityName;
        }

        public string GetCurrentActivityName()
        {
            IAppForm appForm = GetAppForm();
            MyActivityTableEntity myActivity = GetMyActivity();
            if (myActivity == null) return string.Empty;
            return myActivity.K2ActivityName;
        }

        public string GetSourceActionType()
        {
            IAppForm appForm = GetAppForm();
            MyActivityTableEntity myActivity = GetMyActivity();
            if (myActivity == null) return string.Empty;
            return myActivity.SourceActionType;
        }

        public Flow_ProcessConfigTableEntity GetSubmissionProcessConfig()
        {
            if (_submissionProcessConfig == null)
            {
                string procName = GetProcName();
                if (string.IsNullOrEmpty(procName)) return null;
                _submissionProcessConfig = K2DataHelper.GetProcessConfig(procName, ActivityNameConsts.Submission);

            }
            return _submissionProcessConfig;
        }

        public Flow_ProcessConfigTableEntity GetEndProcessConfig()
        {
            if (_endProcessConfig == null)
            {
                string procName = GetProcName();
                if (string.IsNullOrEmpty(procName)) return null;
                _endProcessConfig = K2DataHelper.GetProcessConfig(procName, ActivityNameConsts.End);

            }
            return _endProcessConfig;
        }

        public Flow_ProcessConfigTableEntity GetCurrentProcessConfig()
        {
            if (_currentProcessConfig == null)
            {
                string procName = GetProcName();
                string currentActivityName = GetCurrentActivityName();
                if (string.IsNullOrEmpty(procName) || string.IsNullOrEmpty(currentActivityName)) return null;
                _currentProcessConfig = K2DataHelper.GetProcessConfig(procName, currentActivityName);

            }
            return _currentProcessConfig;
        }

        public Flow_ProcessConfigTableEntity GetRunningProcessConfig()
        {
            if (_runningProcessConfig == null)
            {
                string procName = GetProcName();
                string runningActivityName = GetRunningActivityName();
                if (string.IsNullOrEmpty(procName) || string.IsNullOrEmpty(runningActivityName)) return null;
                _runningProcessConfig = K2DataHelper.GetProcessConfig(procName, runningActivityName);

            }
            return _runningProcessConfig;
        }

        public int GetProcId()
        {
            if (_procId == 0)
            {
                IAppForm appForm = this.GetAppForm();
                if (appForm.ProcInstId > 0)
                {
                    _procId = K2Admin.GetProcID(appForm.ProcInstId);
                }
                else
                {
                    string processName = GetProcessName();
                    _procId = K2Admin.GetDefaultProcID(processName);
                }
            }
            return _procId;
        }

        public K2User GetCurrentUser()
        {
            Dictionary<string, object> formArguments = GetFormArguments();
            int userId;
            string userEn;
            string userCn;
            WorkflowUtility.TryGetDictionaryValue(formArguments, WorkflowKeyConsts.CurrentUserId, out userId);
            WorkflowUtility.TryGetDictionaryValue(formArguments, WorkflowKeyConsts.CurrentUserEn, out userEn);
            WorkflowUtility.TryGetDictionaryValue(formArguments, WorkflowKeyConsts.CurrentUserCn, out userCn);
            return new K2User(userId, userEn, userCn);
        }

        /// <summary>
        /// 当前用户代领导提交或当前用户代领导审批的情况下，该函数取得被代理的领导
        /// </summary>
        /// <returns></returns>
        public K2User GetDelegateFrom()
        {
            Dictionary<string, object> formArguments = GetFormArguments();
            int userId;
            string userEn;
            string userCn;
            WorkflowUtility.TryGetDictionaryValue(formArguments, WorkflowKeyConsts.DelegateFromId, out userId);
            WorkflowUtility.TryGetDictionaryValue(formArguments, WorkflowKeyConsts.DelegateFromEn, out userEn);
            WorkflowUtility.TryGetDictionaryValue(formArguments, WorkflowKeyConsts.DelegateFromCn, out userCn);
            if (userId <= 0) return null;
            return new K2User(userId, userEn, userCn);
        }

        public K2User GetActualUser()
        {
            K2User currentUser = GetCurrentUser();
            K2User delegateFrom = GetDelegateFrom();
            if (delegateFrom == null)
            {
                return currentUser;
            }
            else
            {
                return delegateFrom;
            }
        }

        public K2User GetApplicant()
        {
            return GetAppForm().Applicant;
        }

        public K2User GetReportToOfActualUser()
        {
            if (_reportToOfActualUser == null)
            {
                K2User actualUser = GetActualUser();
                EmployeeTableEntity actualUserEntity = K2DataHelper.GetUserInfoById(actualUser.UserId);
                if (actualUserEntity == null) throw new Exception(string.Format("Failed to GetUserInfoByAccount. account={0}", actualUser));
                string reportToUPI =""; //actualUserEntity.ReportTOUPI;
                EmployeeTableEntitySet set2 = K2DataHelper.GetUserInfoByUSER_CD(reportToUPI);
                if (set2 == null || set2.Count != 1) throw new Exception(string.Format("Failed to GetUserInfoByUSER_CD. user_cd={0}", reportToUPI));
                _reportToOfActualUser = new K2User(set2[0].EmployeeID.Value, set2[0].NameEN, set2[0].NameChinese);
            }
            return _reportToOfActualUser;
        }

        public bool CurrentUserIsCreatorOrApplicant()
        {
            K2User currentUser = GetCurrentUser();
            IAppForm appForm = GetAppForm();
            return currentUser.UserId == appForm.Creator.UserId || currentUser.UserId == appForm.Applicant.UserId;
        }

        /// <summary>
        /// 是否草稿状态
        /// </summary>
        /// <returns></returns>
        public bool IsDraft()
        {
            IAppForm appForm = GetAppForm();
            return string.IsNullOrEmpty(appForm.ProcessStatus) || appForm.ProcessStatus == ProcessStatusConsts.Draft;
        }
        /// <summary>
        /// 是否是提交状态
        /// </summary>
        /// <returns></returns>
        public bool IsSubmitted()
        {
            IAppForm appForm = GetAppForm();
            return appForm.ProcessStatus!=null&&appForm.ProcessStatus == ProcessStatusConsts.Submitted;
        }
        /// <summary>
        /// 是否是Post提交状态
        /// </summary>
        /// <returns></returns>
        public bool IsPostSubmitted()
        {
            IAppForm appForm = GetAppForm();
            return appForm.CurrentStep != null && appForm.CurrentStep == EZVisitActivityNameConsts.Post_Submission;
        }
        /// <summary>
        /// 是否处于流程中
        /// </summary>
        /// <returns></returns>
        public bool IsInProcess()
        {
            return !IsDraft() && !IsEnd();
        }

        /// <summary>
        /// 是否已经结束流程
        /// </summary>
        /// <returns></returns>
        public bool IsEnd()
        {
            return GetAppForm().ProcessStatus == ProcessStatusConsts.End;
        }

        /// <summary>
        /// 是否被拒接
        /// </summary>
        /// <returns></returns>
        public bool IsRejected()
        {
            return GetAppForm().ProcessStatus == ProcessStatusConsts.Rejected;
        }

        /// <summary>
        /// 是否被AskForMore
        /// </summary>
        /// <returns></returns>
        public bool IsAskedForMore()
        {
            return GetAppForm().ProcessStatus == ProcessStatusConsts.AskedForMore;
        }

        /// <summary>
        /// 是否被ForwardBack
        /// </summary>
        /// <returns></returns>
        public bool IsForwardedBack()
        {
            return GetAppForm().ProcessStatus == ProcessStatusConsts.ForwardedBack;
        }

        /// <summary>
        /// 是否由发起人撤回
        /// </summary>
        /// <returns></returns>
        public bool IsWithdrawn()
        {
            return GetAppForm().ProcessStatus == ProcessStatusConsts.Withdrawn;
        }

        public string GetFormTitle()
        {
            //todo: 待实现
            return "FormTitle";
        }

        public string GetActionType()
        {
            IWorkflowPage workflowPage = GetWorkflowPage();
            Dictionary<string, object> formArguments = workflowPage.GetFormArguments();
            string actionType;
            WorkflowUtility.TryGetDictionaryValue(formArguments, WorkflowKeyConsts.ActionType, out actionType);
            return actionType;
        }

        #endregion

        #region IWorkflowController Members

        public void InitActionPanel()
        {
            IWorkflowActionPanel workflowActionPanel = GetWorkflowActionPanel();
            if (workflowActionPanel == null) return;
            List<Button> actionButtonList = workflowActionPanel.GetActionButtonList();
            if (actionButtonList == null) return;

            foreach (Button actionButton in actionButtonList) 
            {
                InitActionButtonVisibilityByDefault(actionButton);
            }

            foreach (Button actionButton in actionButtonList)
            {
                InitActionButtonVisibilityByProcessConfig(actionButton);
            }
            if (!workflowActionPanel.WorkflowButtonVisible)
            {
                foreach (Button actionButton in actionButtonList)
                {
                    if (WorkflowUtility.IsWorkflowRelated(actionButton))
                    {
                        actionButton.Visible = workflowActionPanel.WorkflowButtonVisible;
                    }
                }
            }
            foreach (Button actionButton in actionButtonList)
            {
                InitActionButtonVisibility(actionButton);
            }

            Button btnForward = GetWorkflowPage().GetActionPanel().GetActionButton(K2ActionType.Forward);
            //Button btnForwardBack = GetWorkflowPage().GetActionPanel().GetActionButton(K2ActionType.ForwardBack);
            //btnForwardBack.Visible = btnForward.Visible;

            foreach (Button actionButton in actionButtonList)
            {
                InitActionButtonClientClick(actionButton);
                InitActionButtonAttributes(actionButton);
            }
        }

        public void BuildWorkflowArguments(string actionType)
        {
            IWorkflowPage workflowPage = GetWorkflowPage();
            Dictionary<string, object> formArguments = workflowPage.GetFormArguments();
            formArguments[WorkflowKeyConsts.ActionType] = actionType;

            // 以下ActionType不需要参AuditDestination数
            if (actionType == K2ActionType.ReplyAskForMore || actionType == K2ActionType.ReplyForwardBack || actionType == K2ActionType.Drawback || actionType == K2ActionType.Discard)
            {
                return;
            }

            //AuditDestination参数已经通过Dialog赋值到hidden控件
            if (IsAuditDestinationAssigned())
            {
                return;
            }

            if (actionType == K2ActionType.Reject || actionType == K2ActionType.Withdraw)
            {
                string draftActivityName = GetSubmissionActivityName();
                int creatorId = GetAppForm().Creator.UserId;
                int applicantId = GetAppForm().Applicant.UserId;

                List<int> userList = new List<int>();
                userList.Add(creatorId);
                if (applicantId != creatorId)
                {
                    userList.Add(applicantId);
                }

                K2AuditDestination k2AuditDestination = new K2AuditDestination(draftActivityName, userList.ToArray());

                formArguments[WorkflowKeyConsts.AuditDestination] = k2AuditDestination.ExportText();
                return;
            }
            
            BuildAuditDestinationArgument(actionType);
        }

        public void ExecuteAction()
        {
            string actionType = GetActionType();
            IAppForm appForm = GetAppForm();
            K2Console console = GetK2Console();
            int procInstId = console.Execute();
            IWorkflowPage workflowPage = GetWorkflowPage();
            workflowPage.IsExcuteAction = console.IsExcuteAction;
            if (actionType == K2ActionType.Submit)
            {
                List<K2User> users = new List<K2User>();
                users.Add(appForm.Creator);
                users.Add(appForm.Applicant);
                Dictionary<string, object> formArguments = workflowPage.GetFormArguments();

                K2User chekperson = new K2User(int.Parse(formArguments[EZVisitWorkflowKeyConsts.CODPPCheckPerson].ToString()), "", "");
                users.Add(chekperson);
                K2User manager = new K2User(int.Parse(formArguments[EZVisitWorkflowKeyConsts.CODPPManager].ToString()), "", "");
                users.Add(manager);

                EmployeeTableEntitySet set = K2DataHelper.GetUserInfosByROLE_CD("LGD Check Person");
                foreach (EmployeeTableEntity entity in set)
                {
                    users.Add(new K2User(entity.EmployeeID.Value, entity.NameEN, entity.NameChinese));
                }

                WorkflowUtility.AppendReaders(appForm, users);
            }

            WorkflowUtility.AppendReaders(appForm, console.OutputDestinationUsers);
            ExecuteActionDone();
            if (appForm.ProcInstId <= 0) appForm.ProcInstId = procInstId;
            appForm.UpdateEntity();
        }

        public virtual ActivityLink GetActivityLink()
        {
            return null;
        }

        #endregion

        

        
    }
}
